package com.lz.security.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lz.pojo.SysUser;
import com.lz.security.pojo.LoginUser;
import com.lz.service.SysUserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;

/**
 * jwt工具类
 */
@Slf4j
public class JwtUtil {

    /**
     * 密钥字符串
     */
    private static final String SECRET_KEY = "springSecurity springSecurity springSecurity";

    /**
     * 生成jwt字符串的方法
     */
    public static String generateToken(LoginUser loginUser,long ttl){
        long currentTimeMillis = System.currentTimeMillis();

        return Jwts.builder()
                //在荷载部分中添加自定义的数据
                //添加单个数据
                .claim("loginUser",JsonUtil.toString(loginUser))
                //在荷载部分中添加官方数据
                //唯一标识
                .setId(UUID.randomUUID().toString())
                //签发时间：字符串生成时间
                .setIssuedAt(new Date(currentTimeMillis))
                //签发人
                .setSubject("LZ")
                //过期时间
                .setExpiration(new Date(currentTimeMillis + ttl))
                //设置生成jwt时使用算法和密钥
                .signWith(generalKey(), SignatureAlgorithm.HS256)
                .compact();
    }
    /**
     * 生成jwt字符串的方法 通过手机号
     */
    public static String generateTokenByMobile(String mobile,long ttl){
        long currentTimeMillis = System.currentTimeMillis();

        return Jwts.builder()
                //在荷载部分中添加自定义的数据
                //添加单个数据
                .claim("loginUser",JsonUtil.toString(mobile))
                //在荷载部分中添加官方数据
                //唯一标识
                .setId(UUID.randomUUID().toString())
                //签发时间：字符串生成时间
                .setIssuedAt(new Date(currentTimeMillis))
                //签发人
                .setSubject("LZ")
                //过期时间
                .setExpiration(new Date(currentTimeMillis + ttl))
                //设置生成jwt时使用算法和密钥
                .signWith(generalKey(), SignatureAlgorithm.HS256)
                .compact();
    }
    /**
     * 获取加密密钥对象
     */
    public static SecretKey generalKey(){
        //1.加密密钥字符串的字节数组
        //2.加密算法jcaName
        return new SecretKeySpec(SECRET_KEY.getBytes(),SignatureAlgorithm.HS256.getJcaName());
    }

    /**
     * 解析jwt
     *
     * Claims是payload部分对应的对象
     */
    public static Claims parseToken(String jwtToken){
        Claims claims = Jwts.parserBuilder()
                //设置签名密钥
                .setSigningKey(generalKey())
                .build()
                //设置需要解析的jwt字符串
                .parseClaimsJws(jwtToken)
                .getBody();
        return claims;
    }

    /**
     * 获取登陆用户对象
     */
    public static LoginUser getLoginUser(String jwtToken){
        Claims claims = parseToken(jwtToken);
        String loginUserJson = claims.get("loginUser").toString();
        return JsonUtil.toBean(loginUserJson, LoginUser.class);
    }

    /**
     * 通过手机号获取的token
     * 获取登陆用户对象
     */
    public static LoginUser getLoginUserByMobile(String jwtToken){
        Claims claims = parseToken(jwtToken);
        String mobile = claims.get("loginUser").toString();
        LoginUser loginUser = new LoginUser();
        loginUser.setMobile(mobile);
        return loginUser;
    }

    /**
     * 判断jwt字符串是否过期
     */
    public static boolean isExpire(String jwtToken){
        try {
            Claims claims = parseToken(jwtToken);
            Date expireDate = claims.getExpiration();
            return expireDate.compareTo(new Date()) < 0;
        }catch (ExpiredJwtException e){
            return true;
        }
    }
    /**
     * 测试
     */
    public static void main(String[] args) throws InterruptedException {
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername("jerry");
        loginUser.setMobile("18737859976");
        loginUser.setPercodeList(Arrays.asList("sys:query", "sys:save", "sys:update"));

        String token = generateTokenByMobile(loginUser.getMobile(), 1000*60*60*24);
//        String token = generateToken(loginUser, 500);
        System.out.println(token);

        Thread.sleep(1000);

        System.out.println("是否过期：" + isExpire(token));

        //当jwt字符串没有过期时，获取用户信息
        if(!isExpire(token)){
            LoginUser parseUser = getLoginUserByMobile(token);
            System.out.println(parseUser);
        }else{
            System.out.println("jwt字符串已过期...");
        }
    }

}
